﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RomanNumeralKata.Core.Constants;
using RomanNumeralKata.Core.Utility;

namespace RomanNumeralKata.Core
{
    public class RomanNumeralRecursiveConverter : IRomanNumeralConverter
    {
        private readonly IRomanNumeralValidator _validator;

        public RomanNumeralRecursiveConverter(IRomanNumeralValidator validaor)
        {
            _validator = validaor;
        }

        /// <summary>
        ///     converts arabic number to roman numeral representation using lookup tables
        ///     and integer math, want to make that enumerator smaller
        /// </summary>
        /// <param name="arabicNumber"></param>
        /// <returns></returns>
        public string ConvertArabicToRomanNumeral(int arabicNumber)
        {
            if(arabicNumber > 3999 || arabicNumber < 0) 
                throw new ArgumentOutOfRangeException("arabicNumber", arabicNumber + " was not in the valid range of 0-3999");

            String romanNumeral =
                AccumulateNextNumerals(
                    NumberRepresentations.ArabicToRomanLookup.OrderByDescending(kv => kv.Key).GetEnumerator(),
                    arabicNumber);

            return romanNumeral;
        }

        /// <summary>
        ///     Converts roman numeral to arabic representation
        ///     this can be done a ton of ways
        /// </summary>
        /// <param name="romanNumeral"></param>
        /// <returns></returns>
        public int ConvertRomanNumeralToArabic(string romanNumeral)
        {
            bool isValid = _validator.IsValidRomanNumeral(romanNumeral);
            if (!isValid) throw new InvalidRomanNumeralException(romanNumeral + " is not a valid roman numeral");

            return 0;
        }

        /// <summary>
        ///     this appears to be pretty much the same as looping, if we didn't have a finite list this
        ///     might be better
        /// </summary>
        /// <param name="reverseLookup"></param>
        /// <param name="accumulator"></param>
        /// <returns></returns>
        private string AccumulateNextNumerals(IEnumerator<KeyValuePair<int, string>> reverseLookup, int accumulator)
        {
            if (accumulator == 0) //could use iterator here
                return String.Empty;

            reverseLookup.MoveNext();

            KeyValuePair<int, string> kv = reverseLookup.Current;
            int wholeNumber = accumulator/reverseLookup.Current.Key;
            accumulator -= wholeNumber*kv.Key;

            return kv.Value.PadNumberOfTimes(wholeNumber) + AccumulateNextNumerals(reverseLookup, accumulator);
        }
    }
}